<template>
  <div class="digital-human-container">
    <h1>数字人页面</h1>
    
    

    <div class="wrapper">
      <!-- 数字人渲染区域 -->
    </div>
    <div class="control-panel">
      <!-- <div class="status" :class="{ 'connected': isConnected }">
        状态: {{ isConnected ? '已连接' : '未连接' }}
      </div> -->
      <button @click="startAvatar" class="control-btn">启动数字人</button>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted } from 'vue'

//数字人代码开始
import AvatarPlatform, {
    PlayerEvents as ImportedPlayerEvents,
    SDKEvents,
} from '../avatar-sdk-web_3.1.2.1002/index.js'
// 创建实例 (默认使用内置播放 仅支持 xrtc/webrtc)
const avatarPlatform = new AvatarPlatform()
// 可以选择性 按需 进行相关事件监听
avatarPlatform
    .on(SDKEvents.connected, (initResp: any) => {
        // 获取到拉流地址
        console.log('sdk event: connected', initResp)
    })
    .on(SDKEvents.stream_start, () => {
        // 引擎侧 首帧 推流开始 （注意：不代表端侧已经开始有画面！）
        console.log('sdk event: stream_start')
    })
    .on(SDKEvents.disconnected, (err: any) => {
        setLoading(false)
        console.log('sdk event: disconnected')
        if (err) {
            // 因为异常 而导致的断开！ 此处可以进行 提示通知等
            console.error('ws link disconnected because of Error')
            console.error(e.code, e.message, e.name, e.stack)
        }
    })
    .on(SDKEvents.asr, (asrData: any) => {
        // 监听到语音的识别结果（asr）
        console.log('sdk event: asr', asrData)
    })
    .on(SDKEvents.nlp, (nlpData: any) => {
        // 监听到大模型语义理解结果（nlp）
        console.log('sdk event: nlp', nlpData)
    })
    .on(SDKEvents.frame_start, (frameData: any) => {
        //监听到开始说话的推流首帧
        console.log('sdk event: frameBegin', frameData)
    })
    .on(SDKEvents.tts_duration, (sessionData: any) => {
        console.log('sdk event: duration', sessionData)
    })
    .on(SDKEvents.frame_stop, (frameData: any) => {
        //监听到结束说话的末尾帧
        console.log('sdk event: frameEnd', frameData)
    })
    .on(SDKEvents.error, (error: any) => {
        //监听到错误信息
        console.log('sdk event: error', error)
    })
    .on(SDKEvents.action_start, (actionData: any) => {
        //监听到开始动作的推流首帧
        console.log('sdk event: actionBegin', actionData)
    })
    .on(SDKEvents.action_stop, (actionData: any) => {
        //监听到结束动作的末尾帧
        console.log('sdk event: actionEnd', actionData)
    })
// 可以选择性 按需 进行相关事件监听
const player = avatarPlatform.player || avatarPlatform.createPlayer()
player
    ?.on(ImportedPlayerEvents.play, () => {
        console.log('sdk event: player play')
    })
    .on(ImportedPlayerEvents.waiting, () => {
        console.log('sdk event: player waiting')
    })
    .on(ImportedPlayerEvents.playing, () => {
        console.log('sdk event: player playing')
    })
    .on(ImportedPlayerEvents.playNotAllowed, () => {
        // TODO 由于浏览器限制，如果用户从未对页面进行过交互点击等操作，则无法正常自动播放音视频等
        // 这里需要交互层面引导用户点击屏幕，然后逻辑调用resume 恢复方法
        console.log('sdk event: play not allowed, muted play')
    })


// PlayerEvents 常量枚举
enum PlayerEvents {
    play = 'play',
    waiting = 'waiting',
    playing = 'playing',
    playNotAllowed = 'not-allowed',
}
// 设置api信息
avatarPlatform
    .setApiInfo({
        appId: '67825156',//到交互平台-接口服务中获取，appid需要发布后使用
        apiKey: '54d5fd321b54903c5be42b305541a959',//到交互平台-接口服务中获取
        apiSecret: 'ZDY2YmVmY2Y1MGRmOTczNTA0NzY5NWQ2',//到交互平台-接口服务中获取
        sceneId: '158169337528717312',// //到交互平台-接口服务中获取，传入"接口服务ID"
        serverUrl: 'wss://avatar.cn-huadong-1.xf-yun.com/v1/interact'
    })
    // 设置全局/连接 参数
    .setGlobalParams({
        stream: {
            protocol: 'xrtc',//（必穿）实时视频协议，支持webrtc/xrtc，其中只有xrtc支持透明背景，需参数alpha传1
            alpha: 1,//是否开启透明背景，0关闭1开始，需配合protocol=xrtc使用
        },
        avatar: {
            avatar_id: '110021006', //授权的形象资源id，到交互平台-接口服务-形象列表中获取已授权的形象
            width: 500,
            height: 500,
            mask_region: '[0, 0, 1080, 1920]',
            scale: 1,
            move_h: 0,
            move_v: 0,
            audio_format: 1,
        },
        tts: {
            vcn: 'x4_yezi', //授权的声音资源id，到交互平台-接口服务-声音列表中获取已授权的声音
            speed: 50,
            pitch: 50,
            volume: 100,
        }
    })

// 获取token, 也可以提前获取，在上一步设置
// avatarPlatform
//     .start({
//         wrapper: document.querySelector('.wrapper') as HTMLDivElement
//     })
//     .then(() => {
//         console.log('connected &&  stream play successfully')
//         // 注意这里仅是流可以播放， 如果是进页面在用户未交互网页时，代码自动连，
//         // 第三步骤 player实例 可能收到PlayerEvents.playNotAllowed事件。
//         // 您需要交互层面再次用户点击网页 并主动调用 player.resume() 恢复播放！！
//         // 原因：受限于浏览器的自动播放策略
//     })
//     .catch((e: any) => {
//         // 连接或者流失败，会话停止。
//         console.error(e.code, e.message, e.name, e.stack)
//     })

// 手动启动数字人
function startAvatar() {
  avatarPlatform
    .start({
        wrapper: document.querySelector('.wrapper') as HTMLDivElement
    })
    .then(() => {
        // player.resume()
        console.log('connected &&  stream play successfully')
        // console.log(PlayerEvents.playNotAllowed,666)
        if(PlayerEvents.playNotAllowed == 'not-allowed'){
            player.resume()
            console.log('数字人启动成功')
        }
        // 注意这里仅是流可以播放， 如果是进页面在用户未交互网页时，代码自动连，
        // 第三步骤 player实例 可能收到PlayerEvents.playNotAllowed事件。
        // 您需要交互层面再次用户点击网页 并主动调用 player.resume() 恢复播放！！
        // 原因：受限于浏览器的自动播放策略
    })
    .catch((e: any) => {
        // 连接或者流失败，会话停止。
        console.error(e.code, e.message, e.name, e.stack)
    })
  
  
}

//数字人代码结束



// 组件挂载时不再自动初始化，等待用户交互
onMounted(() => {
  console.log('等待用户交互...')
})

function setLoading(arg0: boolean) {
  throw new Error('Function not implemented.')
}
</script>

<style scoped>
.digital-human-container {
  padding: 20px;
  display: flex;
  flex-direction: column;
  align-items: center;
  position: relative;
}

.interaction-mask {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: rgba(0, 0, 0, 0.7);
  display: flex;
  justify-content: center;
  align-items: center;
  z-index: 1000;
  cursor: pointer;
}

.interaction-content {
  text-align: center;
  color: white;
  padding: 20px;
}

.interaction-content .icon {
  font-size: 48px;
  margin-bottom: 10px;
  animation: bounce 1s infinite;
}

@keyframes bounce {
  0%, 100% {
    transform: translateY(0);
  }
  50% {
    transform: translateY(-10px);
  }
}

.wrapper {
  width: 500px;
  height: 500px;
  border: 1px solid #eee;
  border-radius: 8px;
  overflow: hidden;
  background: #f5f5f5;
}

.control-panel {
  margin-top: 20px;
  padding: 10px;
  border: 1px solid #eee;
  border-radius: 4px;
  display: flex;
  flex-direction: column;
  gap: 10px;
  min-width: 300px;
}

.status {
  padding: 8px 16px;
  border-radius: 4px;
  background-color: #ff4d4f;
  color: white;
  text-align: center;
}

.status.connected {
  background-color: #52c41a;
}

.button-group {
  display: flex;
  gap: 10px;
  justify-content: center;
  margin-top: 10px;
}

.control-btn {
  padding: 8px 20px;
  border: none;
  border-radius: 4px;
  background-color: #1890ff;
  color: white;
  cursor: pointer;
  transition: all 0.3s;
}

.control-btn:hover:not(:disabled) {
  background-color: #40a9ff;
}

.control-btn.stop {
  background-color: #ff4d4f;
}

.control-btn.stop:hover:not(:disabled) {
  background-color: #ff7875;
}

.control-btn:disabled {
  background-color: #d9d9d9;
  cursor: not-allowed;
}
</style> 